package com.example.administrator.qr_code;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.EncodeHintType;
import com.google.zxing.FormatException;
import com.google.zxing.LuminanceSource;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.QRCodeWriter;

import java.util.Hashtable;

public class MainView extends AppCompatActivity {

    private ImageView rImg; //用于存储生成的二维码
    private int rIWid;       //用于记录Image的宽
    private int rIHei;       //用于记录Image的高
    private Button rCreateQRCode;   //【生成二维码】按钮
    private Button rRecoQRCode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_view);
        rCreateQRCode = (Button) findViewById(R.id.Create_QR);
        rCreateQRCode.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EditText editText=(EditText)findViewById(R.id.editText);    //用于获取文本
                createQRCodeImage(editText.getText().toString());
            }
        });
        rRecoQRCode = (Button) findViewById(R.id.Recon_QR);
        rRecoQRCode.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                rImg = (ImageView) findViewById(R.id.Show_QR);
                recognizeQRCode(rImg);
            }
        });
    }

    /**生成二维码函数，参数为字符串str**/
    public void createQRCodeImage(String str){
        rImg = (ImageView)findViewById(R.id.Show_QR);
        rIWid = rImg.getWidth();
        rIHei = rImg.getHeight();
        try
        {
            /*判断str的合法性：非空*/
            if(str==null || "".equals(str) || str.length()<1) return;
            Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();  //创建哈希表，储存键值对
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");   //放入键值对，键为"编码格式" 值为"UTF-8"
            /*图像数据转换，使用了矩阵转换，使用的是Zxing包中类和方法*/
            BitMatrix bitMatrix = new QRCodeWriter().encode(str, BarcodeFormat.QR_CODE, rIWid, rIHei, hints);
            int[] pixels = new int[rIWid * rIHei];  //用于储存二维码各个点的值（0/1），并填充黑白色

            for(int y=0; y<rIHei; y++){
                for(int x=0; x<rIWid; x++){
                    if(bitMatrix.get(x,y)) {
                        pixels[y * rIWid + x] = 0xff000000;//该点填充为黑色
                    }
                    else{
                        pixels[y*rIWid+x]=0xffffffff;//该点填充为白色
                    }
                }
            }
            //生成二维码图片的格式，使用ARGB_8888
            Bitmap bitmap = Bitmap.createBitmap(rIWid, rIHei, Bitmap.Config.ARGB_8888);
            bitmap.setPixels(pixels, 0, rIWid, 0, 0, rIWid, rIHei);
            //显示到ImageView上面
            rImg.setImageBitmap(bitmap);

            /*
            * 整个过程可以理解为：用zxing包中的类和函数，将字符串str利用utf-8的编码格式转换为一个介质bitMatrix（该介质与二维码类似）
            * 然后创建一个二维数组用于储存二维码的每一个点的值
            * 用二维循环读取介质bitMatrix的每一个点的内容：1.该点不为0则将二维数组对应的点置1，在二维码中表现为填充黑色
            *                                              2.该点为0则将二维数组对应的点置0，在二维码中表现为填充白色
            */
        } catch (WriterException e) {
            e.printStackTrace();
        }
    }

    /**解析二维码函数**/
    public void recognizeQRCode(ImageView imageView) {
        Bitmap QRCbmp = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
        int width = QRCbmp.getWidth();
        int height = QRCbmp.getHeight();
        int[] data = new int [width * height];
        QRCbmp.getPixels(data,0,width,0,0,width,height);    //获得像素
        RGBLuminanceSource source = new RGBLuminanceSource(QRCbmp); //获得RGB图
        BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source)); //RGB图转为0、1图
        QRCodeReader qrCodeReader = new QRCodeReader();
        Result result = null; //用于存储识别结果
        try
        {
            result = qrCodeReader.decode(binaryBitmap);
        } catch (FormatException e) {
            e.printStackTrace();
        } catch (ChecksumException e) {
            e.printStackTrace();
        } catch (NotFoundException e) {
            e.printStackTrace();
        }
        Toast.makeText(this, result.getText(), Toast.LENGTH_LONG).show();
    }

    /*解析二维码所用到的类 RGBLuminanceSource*/
    public class RGBLuminanceSource extends LuminanceSource{

        private byte bitmapPixels[];

        protected RGBLuminanceSource(Bitmap bitmap) {  //重构构造函数
            super(bitmap.getWidth(), bitmap.getHeight());
            // 首先，要取得该图片的像素数组内容
            int[] data = new int[bitmap.getWidth() * bitmap.getHeight()];
            this.bitmapPixels = new byte[bitmap.getWidth() * bitmap.getHeight()];
            bitmap.getPixels(data, 0, getWidth(), 0, 0, getWidth(), getHeight());

            // 将int数组转换为byte数组，也就是取像素值中蓝色值部分作为辨析内容
            for (int i = 0; i < data.length; i++) {
                this.bitmapPixels[i] = (byte) data[i];
            }

        }

        @Override
        public byte[] getRow(int i, byte[] bytes) {
            // 这里要得到指定行的像素数据
            System.arraycopy(bitmapPixels, i * getWidth(), bytes, 0, getWidth());
            return bytes;

        }

        @Override
        public byte[] getMatrix() {
            return bitmapPixels;
        }
    }

}
